﻿using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;

namespace AutoCADDotNetLibrary.Analyzers.Analyzers
{
    [DiagnosticAnalyzer(LanguageNames.CSharp)]
    public class CommandMethodAttributeAnalyzer : DiagnosticAnalyzer
    {
        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(ACDiagnostic.Rule_AC0002);

        public override void Initialize(AnalysisContext context)
        {
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            context.EnableConcurrentExecution();
            context.RegisterCompilationStartAction(compilationStartAnalysisContext =>
            {
                //得到所有命令方法
                List<(string Command, Location Location)> commandList = new List<(string Command, Location Location)>();
                compilationStartAnalysisContext.RegisterSymbolAction(symbolAnalysisContext =>
                {
                    AttributeData att = symbolAnalysisContext.Symbol.GetAttributes()
                     .Where(x => x.AttributeClass.ToDisplayString() == "Autodesk.AutoCAD.Runtime.CommandMethodAttribute").FirstOrDefault();

                    if (att == null)
                        return;

                    if (att.ConstructorArguments.Length <= 2)
                    {
                        commandList.Add((att.ConstructorArguments[0].Value?.ToString() ?? "",
                            att.ApplicationSyntaxReference.GetSyntax().GetLocation()));
                    }
                    else
                    {
                        commandList.Add((att.ConstructorArguments[1].Value?.ToString() ?? "",
                            att.ApplicationSyntaxReference.GetSyntax().GetLocation()));
                    }
                }, SymbolKind.Method);

                //判断
                compilationStartAnalysisContext.RegisterCompilationEndAction(symbolAnalysisContext =>
                {
                    commandList.GroupBy(x => x.Command.Trim().ToLower()).Where(x => x.Count() > 1)
                    .SelectMany(x => x).ToList().ForEach(x =>
                    {
                        symbolAnalysisContext.ReportDiagnostic(
                            Diagnostic.Create(ACDiagnostic.Rule_AC0002, x.Location, x.Command));
                    });
                });
            });
        }
    }
}